package com.lanyam.travel.base.controller;


import com.lanyam.travel.base.entity.CashSetting;
import com.lanyam.travel.base.entity.vo.DistrUserVo;
import com.lanyam.travel.base.exception.NoTicketException;
import com.lanyam.travel.base.service.ICashSettingService;
import com.lanyam.travel.base.service.IDistrUserService;
import com.lanyam.travel.base.utils.*;
import com.lanyam.travel.base.entity.CashRecord;
import com.lanyam.travel.base.entity.vo.CashRecordVo;
import com.lanyam.travel.base.service.ICashRecordService;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import com.fasterxml.jackson.core.type.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;


@RestController
@RequestMapping("/cashRecord")
public class CashRecordController {

    @Autowired
    private ICashRecordService cashRecordService;

    @Autowired
    private ICashSettingService cashSettingService;

    @Autowired
    private IDistrUserService distrUserService;

    /**
     * 分页查询数据
     */
    @GetMapping("/getPage")
    public IPage<CashRecordVo> getPage (String queryMap,
                                                @RequestParam(name="page", defaultValue = "1") Integer page,
                                                @RequestParam(name="rows", defaultValue = "10") Integer rows) {
        Map<String, Object> query = JsonMapper.string2Obj(queryMap,new TypeReference<Map<String, Object>>() {});
        IPage<CashRecordVo> pageInfo = cashRecordService.getPageCashRecord(query, page, rows);
        return pageInfo;
    }

    /**
     * 微信端查询
     * @param reqMap
     * @return
     */
    @RequestMapping(value="/query", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public JSONResult query (@RequestBody(required = false) Map<String,Object> reqMap) {
        Map<String,Object> map = (Map<String, Object>) reqMap.get("reqMap");
        Integer pageNum = Integer.parseInt(map.get("page").toString());
        Integer pageSize = Integer.parseInt(map.get("pageSize").toString());
        String userId = map.get("userId").toString();
        IPage<CashRecordVo> pageInfo = cashRecordService.getPageCashRecord(map, pageNum, pageSize);
        return JSONResult.ok(pageInfo);
    }

    /**
     * 新增数据
     */
    @PostMapping("/add")
    public JSONResult add (@RequestBody CashRecord cashRecord) {
        JSONResult result = null;
        try{
            cashRecordService.addCashRecord(cashRecord);
            result = JSONResult.ok();
        }  catch (Exception e) {
            e.printStackTrace();
            String msg = e.getMessage();
            result = JSONResult.errorMsg(msg);
        }
        return result;
    }



    /**
     * 编辑数据
     */
    @PostMapping("/update")
    public JSONResult update (@RequestBody CashRecord cashRecord) {
        JSONResult result = null;
        try{
            cashRecordService.updateCashRecord(cashRecord);
            result = JSONResult.ok();
        }  catch (Exception e) {
            e.printStackTrace();
            String msg = e.getMessage();
            result = JSONResult.errorMsg(msg);
        }
        return result;
    }

    /**
     * 删除数据
     */
    @PostMapping("/delById")
    public JSONResult delById (String id) {
        JSONResult result = null;
        try {
            cashRecordService.delById(id);
            result = JSONResult.ok();
        }  catch (Exception e) {
            e.printStackTrace();
            String msg = e.getMessage();
            result = JSONResult.errorMsg(msg);
        }
        return result;
    }

    /**
     * 提现
     * @param userId
     * @param userName
     * @param amount
     * @return
     */
    @PostMapping("/cashWithDraw")
    @Transactional(rollbackFor = NoTicketException.class)
    public JSONResult cashWithDraw(String userId, String userName, BigDecimal amount,HttpServletRequest request){
        try {
            CashSetting settingData = cashSettingService.getSettingData();//提现设置
            int compareResult = settingData.getAllowCash().compareTo(amount);
            BigDecimal charge = new BigDecimal(0);//手续费
            if(compareResult==0){
                //提现门槛等于提现金额
                charge = amount.multiply(settingData.getServCharge());
            }else if(compareResult==-1){
                //提现门槛小于提现金额
                charge = amount.multiply(settingData.getServCharge());
            }else if(compareResult==1){
                //提现门槛大于提现金额
                charge = settingData.getLowerServCharge();
            }
            if(charge.compareTo(amount)==1){
                return JSONResult.errorMsg("提现金额有误，手续费用大于提现金额");
            }
            String id = UUID.randomUUID().toString().replace("-", "");
            Map result = wechatCashWithDraw(id,userId,userName,amount.doubleValue(),request);//微信体现，返回
            String return_code = (String) result.get("return_code");//返回状态码
            String result_code = (String) result.get("result_code");//返回状态码
            int status=1;
            if(result_code.equals("FAIL")){
                //线上提现失败
                status = 0;
                //return JSONResult.errorMsg(result.get("return_msg").toString());
            }
            CashRecord cashRecord = new CashRecord();
            cashRecord.setId(id);
            cashRecord.setAmount(amount.subtract(charge));
            cashRecord.setUserId(userId);
            cashRecord.setUserName(userName);
            cashRecord.setCreateTime(new Date());
            cashRecord.setStatus(status);
            cashRecord.setCharge(charge);
            cashRecordService.addCashRecord(cashRecord);
            //提现完成后减去分销用户可提现金额
//            if(status==0) {
                DistrUserVo vo = distrUserService.getDistrUserByUserId(userId);
                vo.setAmount(vo.getAmount().subtract(amount));
                distrUserService.updateDistrUser(vo);
//            }
            if(result_code.equals("FAIL")){
                return JSONResult.errorMsg(result.get("return_msg").toString()+"，请前往门店提现");
            }else {
                return JSONResult.ok("提现成功");
            }
        }catch(Exception e){
            return JSONResult.errorMsg("提现设置获取异常");
        }
    }

    /**
     * 提现
     * @param openId
     * @param request
     * @return
     */
    private static Map wechatCashWithDraw(String transActionId,String openId,String userName,Double amount,HttpServletRequest request) {
        try {
            //生成的随机字符串
            String nonce_str = WXCodeUtil.getRandomStringByLength(32);
            //获取客户端的ip地址
            String spbill_create_ip = WXCodeUtil.getIpAddr(request);

            //组装参数，用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap<>();
            packageParams.put("mch_appid", Constant.APP_ID);
            packageParams.put("mchid", Constant.MCH_ID);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("partner_trade_no",transActionId);
            packageParams.put("openid",openId);
            packageParams.put("check_name","NO_CHECK");
            packageParams.put("re_user_name",userName);
            packageParams.put("amount","1");
            packageParams.put("desc","金额提现");
            packageParams.put("spbill_create_ip",spbill_create_ip);

            String prestr = PayUtil.createLinkString(packageParams);           // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String mysign = PayUtil.sign(prestr, Constant.key, "utf-8").toUpperCase(); //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            //
            String xml = "<xml>"
                    + "<mch_appid><![CDATA[" + Constant.APP_ID + "]]></mch_appid>"
                    + "<mchid><![CDATA[" + Constant.MCH_ID + "]]></mchid>"
                    + "<nonce_str><![CDATA[" + nonce_str + "]]></nonce_str>"
                    + "<partner_trade_no><![CDATA[" + transActionId + "]]></partner_trade_no>"
                    + "<openid><![CDATA[" + openId + "]]></openid>"
                    + "<check_name><![CDATA[NO_CHECK]]></check_name>"
                    + "<re_user_name><![CDATA[" + userName + "]]></re_user_name>"
                    + "<amount><![CDATA[" + 1 + "]]></amount>"//支付的金额，单位：分
                    + "<desc><![CDATA[金额提现]]></desc>"
                    + "<spbill_create_ip><![CDATA[" + spbill_create_ip + "]]></spbill_create_ip>"
                    + "<sign><![CDATA[" + mysign + "]]></sign>"
                    + "</xml>";
            //提现接口
            String result = doRefund(Constant.WITHDRAW_PAY_URL, xml);
            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);
            return map;
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 申请退款
    */
    public static String doRefund(String url, String data) throws Exception {
        String PKCS12 = Constant.MCH_ID;
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        File file =new File("src/main/resources/matkeycert/apiclient_cert.p12");
        System.out.println(file.length());
        FileInputStream is = new FileInputStream(file);
        try {
            keyStore.load(is, PKCS12.toCharArray());
        } finally {
            is.close();
        }
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,PKCS12.toCharArray()).build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[]{"TLSv1"},null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }
}